// 服务端监听
package server

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"gitee.com/xgotool/sqlite-logs-more/service/rootdb"
	"github.com/gin-gonic/gin"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
)

// Gin框架路由拦截器-COSR请求头添加
var CORS gin.HandlerFunc = func(c *gin.Context) {
	method := c.Request.Method
	c.Set("uid", uint(1)) // 设置登录用户ID，避免依赖中因用户权限被拒
	c.Header("Access-Control-Allow-Origin", "*")
	c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
	c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization")
	c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
	c.Header("Access-Control-Allow-Credentials", "true")
	if method == "OPTIONS" {
		c.AbortWithStatus(http.StatusNoContent)
	}
	c.Next()
}

// 日志记录拦截器
//
//	ctx		请求的参数体，用于提取变量、注入变量等操作
//	req		请求参数，*xgrpc.Request 类型（xgrec框架下类型）
//	info	请求的结构信息等
//	handle	下一步请求的方法，调用为：handler(ctx, req)
func grpcLoggerInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
	t := time.Now()
	resp, err = handler(ctx, req)
	// bodys, _ := json.Marshal(resp)
	// xlog.Quest(&https.CURL{
	// 	Uri:       info.FullMethod,
	// 	ParamJson: map[string]any{"_": req},
	// 	Body:      string(bodys),
	// 	StartTime: t,
	// 	EndTime:   time.Now(),
	// 	Error:     err,
	// })
	fmt.Printf("gRpc quest method: %s | rssp: %v | req: %s | time: %s | durations: %s | did: %d\n",
		info.FullMethod, resp, req, t.Format(time.DateTime), time.Since(t), ctx.Value("_did"),
	)
	return
}

// 异常恢复拦截器
//
//	ctx		请求的参数体，用于提取变量、注入变量等操作
//	req		请求参数，*xgrpc.Request 类型（xgrec框架下类型）
//	info	请求的结构信息等
//	handle	下一步请求的方法，调用为：handler(ctx, req)
func grpcRecoveryInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
	defer func() {
		if e := recover(); e != nil {
			// switch err := e.(type) {
			// case error:
			// 	xlog.Panic("GRPC出现异常", err)
			// }
			fmt.Println("panic.recover: ", e)
		}
	}()
	resp, err = handler(ctx, req)
	return
}

// 安全认证拦截器
//
//	ctx		请求的参数体，用于提取变量、注入变量等操作
//	req		请求参数，*xgrpc.Request 类型（xgrec框架下类型）
//	info	请求的结构信息等
//	handle	下一步请求的方法，调用为：handler(ctx, req)
func grpcAuthInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
	// 获取请求客户端的IP
	ip := ClientIp(ctx)
	// 解析metada中的信息并验证
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return nil, status.Errorf(codes.Unauthenticated, "无Token认证信息")
	}
	var (
		appid  string
		appkey string
		mac    string
	)
	if val, ok := md["appid"]; ok {
		appid = val[0]
	}
	if val, ok := md["appkey"]; ok {
		appkey = val[0]
	}
	if macs, ok := md["mac"]; ok {
		mac = macs[0]
	}
	if appid != "appid" || appkey != "appkey" {
		return nil, status.Errorf(codes.Unauthenticated, "Token认证信息无效: appid=%s, appkey=%s", appid, appkey)
	}
	if mac == "" {
		return nil, status.Errorf(codes.Unauthenticated, "MAC地址获取为空")
	}
	// 获取MAC地址信息
	macs := map[string]string{}
	if err = json.Unmarshal([]byte(mac), &macs); err != nil {
		return nil, status.Errorf(codes.Unauthenticated, err.Error())
	}
	// 获取用户的设备ID
	dinfo, err := rootdb.DerviceInfoByMac(macs, ip.Ip)
	if err != nil {
		return nil, status.Errorf(codes.Unauthenticated, err.Error())
	}
	// 如果要注入用户ID等的话需要在此处进行注入
	ctx = context.WithValue(ctx, "_did", dinfo.Id)
	resp, err = handler(ctx, req)
	return
}
